<template>
  <scroll-view class="media-view" scroll-y @scrolltolower="() => loadMediaList()">
    <view class="items" v-if="mediaList.length || loading">
      <view class="media-item" :class="{active: mediaItem.active, selected: mediaItem.selected}"
        v-for="(mediaItem, index) in mediaList" @click="onSelect(index)" :key="mediaItem.id">
        <view class="image">
          <image :src="mediaItem.thumbUrl || '/static/file.png'" mode="widthFix" class="img" />
          <view class="name">{{thumbName(mediaItem.name)}}</view>
        </view>
      </view>
    </view>

    <view class="media-library-isnull" v-else>
      <uni-icons type="images" size="60" color="#ccc"></uni-icons>
      <view class="text">资源库为空，是否上传资源？</view>
      <button type="primary" size="mini" @click="$emit('onUploadMedia');">上传媒体资源</button>
    </view>

  </scroll-view>
</template>

<script>
  import {
    mapActions
  } from 'vuex';
  export default {
    name: "media-list",
    emits: ['onSelect', 'onUploadMedia'],
    expose: ['cancelAllSelected', 'deleteSelectedMedia', 'loadMediaList'],
    props: {
      mediaType: {
        type: String,
        default: () => "all"
      },
      mediaGroup: String,
      keyword: String,
      selectedCount: Number
    },
    data() {
      return {
        page: 1,
        loading: false,
        lastSelectedIndex: 0,
        mediaList: [],
        shiftKey: false,
      }
    },
    watch: {
      mediaType(){
        this.loadMediaList(true)
      },
      mediaGroup() {
        this.loadMediaList(true)
      },
      keyword() {
        this.loadMediaList(true)
      }
    },

    mounted() {
      this.loadMediaList()
      // #ifdef H5
      document.addEventListener('keydown', this.onKeyDown)
      document.addEventListener('keyup', this.onKeyUp)
      // #endif
    },
    destroyed() {
      // #ifdef H5
      document.removeEventListener('keydown', this.onKeyDown)
      document.removeEventListener('keyup', this.onKeyUp)
      // #endif
    },
    methods: {
      ...mapActions('source', ['list']),
      thumbName(name) {
        let list = name.split(".");
        let ext = list.pop();

        return list.join(".").substr(0, 8) + '...' + "." + ext
      },
      onKeyDown(e) {
        if (e.keyCode === 16) {
          this.shiftKey = true
        }
      },
      onKeyUp(e) {
        if (e.keyCode === 16) {
          this.shiftKey = false
        }
      },
      loadMediaList(reset = false) {
        if(this.loading){
          return;
        }
        this.loading = true

        // 重新加载媒体库列表清空上传列表
        if (reset) {
          this.mediaList = []
          this.page = 1;
          this.cancelAllSelected()
        }

        this.list({
          page: this.page,
          limit: 30,
          type: this.mediaType,
          keyword: this.keyword
        }).then(data => {
          if (data.list.length == 0) {
            this.page--
          } else {
            this.mediaList = this.mediaList.concat(data.list)
          }

          this.loading = false;
        });

        this.page++;
      },
      onSelect(index) {
        if (this.isUploading) return

        let minIndex = index
        let maxIndex = index
        // shift 多选
        if (this.shiftKey) {
          minIndex = Math.min(this.lastSelectedIndex, index)
          maxIndex = Math.max(this.lastSelectedIndex, index)
        }

        const mediaItem = this.mediaList[index]

        // 如果设置了最大选择数量，判断是否超过最大数量
        if (this.selectedCount > 0 && !mediaItem.selected && !mediaItem.active) {
          const selectedMediaCount = this.mediaList.reduce((count, item) => item.selected || item.active ? count + 1 :
            count, 0)
          if (selectedMediaCount + (maxIndex - minIndex + 1) > this.selectedCount) {
            uni.showToast({
              title: `最多只能选择${this.selectedCount}个媒体文件`,
              icon: 'none'
            })
            return
          }
        }

        // 选择
        if (!mediaItem.selected) {
          // 选中当前
          for (let i = minIndex; i <= maxIndex; i++) {
            this.$set(this.mediaList[i], 'active', !mediaItem.active)
          }

          // 取消其他当前选中并设置为已选择
          for (const otherMediaItem of this.mediaList) {
            if (otherMediaItem.active && otherMediaItem.id !== mediaItem.id) {
              this.$set(otherMediaItem, 'active', false)
              this.$set(otherMediaItem, 'selected', true)
            }
          }
        } else {
          // 取消选择
          this.$set(this.mediaList[index], 'selected', false)
        }

        this.lastSelectedIndex = index

        this.$nextTick(() => {
          this.$emit('onSelect', this.mediaList.filter(item => item.selected || item.active))
        })
      },
      cancelAllSelected() {

        for (const mediaItem of this.mediaList) {
          if (mediaItem.active || mediaItem.selected) {
            this.$set(mediaItem, 'active', false)
            this.$set(mediaItem, 'selected', false)
          }
        }
        this.$nextTick(() => {
          this.$emit('onSelect', [])
        })
      },
      deleteSelectedMedia(mediaIds) {
        
        for (const id of mediaIds) {
          const index = this.mediaList.findIndex(item => item.id === id)
          this.mediaList.splice(index, 1)
        }
        

        this.$nextTick(() => {
          this.$emit('onSelect', [])
        })
      }
    }
  }
</script>

<style lang="scss">
  .media-view {
    flex: 1;
    margin-top: 10px;
    overflow-y: auto;
    height: 100%;

    .items {
      display: flex;
      flex-wrap: wrap;
      gap: 10px;
      padding-bottom: 20px;
    }
  }

  .loading {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;

    .icon {
      animation: rotate 1s linear infinite;
    }
  }

  .media-item {
    --row-media-item: 7;
    width: calc(100% / var(--row-media-item) - (((var(--row-media-item) - 1) * 10px) / (var(--row-media-item)) + 0.01px));
    border: #f5f5f5 solid 5px;
    border-radius: 6px;
    box-sizing: border-box;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    transition: border-color .25s;

    &.selected {
      border-color: rgba(41, 121, 255, .5);
    }

    &.active {
      border-color: #2979ff;
    }

    .image {
      height: 0;
      position: relative;
      height: 100%;

      .img {
        width: 100%;
        height: 100%;
        border-radius: 4px;
      }

      .name {
        width: calc(100% - 40rpx);
        font-size: 12px;
        color: #57606f;
        overflow: hidden;
        text-overflow: hidden;
        white-space: nowrap;
        margin: 0 20rpx;
        text-align: center;
      }
    }

    .mask {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      z-index: 1;
      background: rgba(0, 0, 0, .5);
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;

      .tip {
        font-size: 12px;
        color: #fff;
        margin-top: 5px;
      }
    }

    .progress {
      width: 80%;
      height: 4px;
      border-radius: 2px;
      background: #fff;
      position: relative;
      overflow: hidden;

      .inner {
        width: 0;
        height: 100%;
        border-radius: 2px;
        transition: width .3s;
        background: #2979ff;
      }
    }
  }

  .media-library-isnull {
    padding-top: 50px;
    text-align: center;

    .text {
      font-size: 18px;
      color: #ccc;
      margin-top: 5px;
      margin-bottom: 30px;
    }
  }

  @keyframes rotate {
    0% {
      transform: rotate(0deg);
    }

    100% {
      transform: rotate(360deg)
    }
  }

  @media screen and (max-width: 768px) {
    .media-item {
      --row-media-item: 3;
    }
  }

  @media screen and (min-width: 768px) {
    .media-item {
      --row-media-item: 5;
    }
  }

  @media screen and (min-width: 1360px) {
    .media-item {
      --row-media-item: 7;
    }
  }

  @media screen and (min-width: 1920px) {
    .media-item {
      --row-media-item: 10;
    }
  }

  @media screen and (min-width: 2560px) {
    .media-item {
      --row-media-item: 15;
    }
  }
</style>